home *** CD-ROM | disk | FTP | other *** search
/ Complete Linux / Complete Linux.iso / docs / apps / database / postgres / postgre4.z / postgre4 / src / lib / C / equalfuncs.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-08-27  |  16.0 KB  |  796 lines

  1. #include "tmp/postgres.h"
  2.  
  3. RcsId("$Header: /private/postgres/src/lib/C/RCS/equalfuncs.c,v 1.27 1992/07/26 17:09:30 mer Exp $");
  4.  
  5. #include "nodes/nodes.h"
  6. #include "nodes/primnodes.h"
  7. #include "nodes/relation.h"
  8. #include "nodes/execnodes.h"
  9. #include "nodes/plannodes.h"
  10.  
  11. #include "utils/log.h"
  12. #include "storage/itemptr.h"
  13. #include "lib/equalfuncs.h"
  14.  
  15. bool
  16. equal(a, b)
  17.     Node    a;
  18.     Node    b;
  19. {
  20.     if (a == b)
  21.       return(true);
  22.     if ((!a && b) || (a && !b))
  23.       return(false);
  24.     Assert(IsA(a,Node));
  25.     Assert(IsA(b,Node));
  26.     if (a->type != b->type)
  27.       return (false);
  28.     
  29.     return ((a->equalFunc)(a, b));
  30. }
  31.  
  32. /*
  33.  *  Stuff from primnodes.h
  34.  */
  35.  
  36. /*
  37.  *  Resdom is a subclass of Node.
  38.  */
  39.  
  40. bool
  41. _equalResdom(a, b)
  42.     register Resdom    a;
  43.     register Resdom    b;
  44. {
  45.     register OperatorTupleForm at;
  46.     register OperatorTupleForm bt;
  47.  
  48.     if (a->resno != b->resno)
  49.         return (false);
  50.     if (a->restype != b->restype)
  51.         return (false);
  52.     if (a->rescomplex != b->rescomplex)
  53.             return(false);
  54.     if (a->reslen != b->reslen)
  55.         return (false);
  56.     if (strcmp(a->resname, b->resname) != 0)
  57.         return (false);
  58.     if (a->reskey != b->reskey)
  59.         return (false);
  60.  
  61.     /*
  62.      *  reskeyop is a pointer to an OperatorTupleForm.  We can almost
  63.      *  do a bcmp() on the two structures, but the oprname field is
  64.      *  a char16, and bytes after the null may not be the same.  We
  65.      *  do all this by hand because of that.
  66.      */
  67.     at = a->reskeyop;
  68.     bt = b->reskeyop;
  69.  
  70.     /* well, it might happen... */
  71.     if (at == bt)
  72.         return (true);
  73.  
  74.     if (strncmp(at->oprname, bt->oprname, sizeof (bt->oprname)) != 0)
  75.         return (false);
  76.     if (at->oprowner != bt->oprowner)
  77.         return (false);
  78.     if (at->oprprec != bt->oprprec)
  79.         return (false);
  80.     if (at->oprkind != bt->oprkind)
  81.         return (false);
  82.     if (at->oprisleft != bt->oprisleft)
  83.         return (false);
  84.     if (at->oprcanhash != bt->oprcanhash)
  85.         return (false);
  86.     if (at->oprleft != bt->oprleft)
  87.         return (false);
  88.     if (at->oprright != bt->oprright)
  89.         return (false);
  90.     if (at->oprresult != bt->oprresult)
  91.         return (false);
  92.     if (at->oprcom != bt->oprcom)
  93.         return (false);
  94.     if (at->oprnegate != bt->oprnegate)
  95.         return (false);
  96.     if (at->oprlsortop != bt->oprlsortop)
  97.         return (false);
  98.     if (at->oprrsortop != bt->oprrsortop)
  99.         return (false);
  100.     if (at->oprcode != bt->oprcode)
  101.         return (false);
  102.     if (at->oprrest != bt->oprrest)
  103.         return (false);
  104.     if (at->oprjoin != bt->oprjoin)
  105.         return (false);
  106.  
  107.     return (true);
  108. }
  109.  
  110. bool
  111. _equalFjoin(a, b)
  112.     Fjoin a;
  113.     Fjoin b;
  114. {
  115.     int nNodes;
  116.  
  117.     if (a->fj_initialized != b->fj_initialized)
  118.         return (false);
  119.     if (a->fj_nNodes != b->fj_nNodes)
  120.         return (false);
  121.     if (!equal((Node)a->fj_innerNode, (Node)b->fj_innerNode))
  122.         return (false);
  123.     
  124.     nNodes = a->fj_nNodes;
  125.     if (bcmp(a->fj_results, b->fj_results, nNodes*sizeof(Datum)) != 0)
  126.         return (false);
  127.     if (bcmp(a->fj_alwaysDone, b->fj_alwaysDone, nNodes*sizeof(bool)) != 0)
  128.         return (false);
  129.  
  130.     return(true);
  131. }
  132. /*
  133.  *  Expr is a subclass of Node.
  134.  */
  135. bool
  136. _equalExpr(a, b)
  137.     Expr    a;
  138.     Expr    b;
  139. {
  140.     /* no private data */
  141.     return (true);
  142. }
  143.  
  144. bool
  145. _equalIter(a, b)
  146.     Iter    a;
  147.     Iter    b;
  148. {
  149.     return (equal((Node)a->iterexpr, (Node)b->iterexpr));
  150. }
  151.  
  152. /*
  153.  *  Var is a subclass of Expr.
  154.  */
  155.  
  156. bool
  157. _equalVar(a, b)
  158.     register Var    a;
  159.     register Var    b;
  160. {
  161.     if (!_equalExpr((Expr)a, (Expr)b))
  162.         return (false);
  163.  
  164.     if (a->varno != b->varno)
  165.         return (false);
  166.     if (a->varattno != b->varattno)
  167.         return (false);
  168.     if (a->vartype != b->vartype)
  169.         return (false);
  170.     if (!_equalLispValue(a->varid, b->varid))
  171.         return (false);
  172.  
  173.     return (true);
  174. }
  175.  
  176. bool
  177. _equalArray(a, b)
  178.     register Array    a;
  179.     register Array    b;
  180.  
  181. {
  182.     if (!_equalExpr((Expr)a, (Expr)b))
  183.         return (false);
  184.     if (a->arrayelemtype != b->arrayelemtype)
  185.         return (false);
  186.     if (a->arraylow != b->arraylow)
  187.         return (false);
  188.     if (a->arrayhigh != b->arrayhigh)
  189.         return (false);
  190.     if (a->arraylen != b->arraylen)
  191.         return (false);
  192.     return(true);
  193. }
  194.  
  195. bool
  196. _equalArrayRef(a, b)
  197.     register ArrayRef    a;
  198.     register ArrayRef    b;
  199.  
  200. {
  201.     if (!_equalExpr((Expr)a, (Expr)b))
  202.         return (false);
  203.     if (a->refelemtype != b->refelemtype)
  204.         return (false);
  205.     if (a->refattrlength != b->refattrlength)
  206.         return (false);
  207.     if (a->refelemlength != b->refelemlength)
  208.         return (false);
  209.     if (a->refelembyval != b->refelembyval)
  210.         return (false);
  211.     if (!_equalLispValue(a->refindexpr, b->refindexpr))
  212.         return (false);
  213.  
  214.     return (_equalLispValue(a->refexpr, b->refexpr));
  215. }
  216.  
  217. /*
  218.  *  Oper is a subclass of Expr.
  219.  */
  220.  
  221. bool
  222. _equalOper(a, b)
  223.     register Oper    a;
  224.     register Oper    b;
  225. {
  226.     if (!_equalExpr((Expr)a, (Expr)b))
  227.         return (false);
  228.  
  229.     if (a->opno != b->opno)
  230.         return (false);
  231.     if (a->oprelationlevel != b->oprelationlevel)
  232.         return (false);
  233.     if (a->opresulttype != b->opresulttype)
  234.         return (false);
  235.  
  236.     return (true);
  237. }
  238.  
  239. /*
  240.  *  Const is a subclass of Expr.
  241.  */
  242.  
  243. bool
  244. _equalConst(a, b)
  245.     register Const    a;
  246.     register Const    b;
  247. {
  248.     /*
  249.     ** this function used to do a pointer compare on a and b.  That's
  250.     ** ridiculous.  -- JMH, 7/11/92
  251.     */
  252.     if (a->consttype != b->consttype)
  253.       return(false);
  254.     if (a->constlen != b->constlen)
  255.       return(false);
  256.     if (a->constisnull != b->constisnull)
  257.       return(false);
  258.     if (a->constbyval != b->constbyval)
  259.       return(false);
  260.     return(datumIsEqual(a->constvalue, b->constvalue,
  261.                 a->consttype, a->constbyval, a->constlen));
  262. }
  263.  
  264. /*
  265.  *  Param is a subclass of Expr.
  266.  */
  267.  
  268. bool
  269. _equalParam(a, b)
  270.     register Param    a;
  271.     register Param    b;
  272. {
  273.     if (!_equalExpr((Expr) a, (Expr) b))
  274.         return (false);
  275.  
  276.     if (a->paramkind != b->paramkind)
  277.         return (false);
  278.     if (a->paramtype != b->paramtype)
  279.         return (false);
  280.     if (!equal((Node)a->param_tlist, (Node)b->param_tlist))
  281.               return (false);
  282.  
  283.     switch (a->paramkind) {
  284.         case PARAM_NAMED:
  285.         case PARAM_NEW:
  286.         case PARAM_OLD:
  287.         if (strcmp(a->paramname, b->paramname) != 0)
  288.             return (false);
  289.         break;
  290.         case PARAM_NUM:
  291.         if (a->paramid != b->paramid)
  292.             return (false);
  293.         break;
  294.         case PARAM_INVALID:
  295.         /*
  296.          * XXX: Hmmm... What are we supposed to return
  297.          * in this case ??
  298.          */
  299.         return(true);
  300.         break;
  301.         default:
  302.         elog(WARN, "_equalParam: Invalid paramkind value: %d",
  303.         a->paramkind);
  304.     }
  305.  
  306.     return (true);
  307. }
  308.  
  309. /*
  310.  *  Func is a subclass of Expr.
  311.  */
  312.  
  313. bool
  314. _equalFunc(a, b)
  315.     register Func    a;
  316.     register Func    b;
  317. {
  318.     if (!_equalExpr((Expr) a, (Expr) b))
  319.         return (false);
  320.  
  321.     if (a->funcid != b->funcid)
  322.         return (false);
  323.     if (a->functype != b->functype)
  324.         return (false);
  325.     if (a->funcisindex != b->funcisindex)
  326.         return (false);
  327.     if (a->funcsize != b->funcsize)
  328.         return (false);
  329.     if (!equal((Node)a->func_tlist, (Node)b->func_tlist))
  330.         return (false);
  331.     if (!equal((Node)a->func_planlist, (Node)b->func_planlist))
  332.         return (false);
  333.  
  334.     return (true);
  335. }
  336.  
  337. /*
  338.  * CInfo is a subclass of Node.
  339.  */
  340.  
  341. bool
  342. _equalCInfo(a,b)
  343.      register CInfo a;
  344.      register CInfo b;
  345. {
  346.     Assert(IsA(a,CInfo));
  347.     Assert(IsA(b,CInfo));
  348.     
  349.     if (!_equalLispValue((LispValue)(get_clause(a)),
  350.              (LispValue)(get_clause(b))))
  351.       return(false);
  352.     if (a->selectivity != b->selectivity)
  353.       return(false);
  354.     if (a->notclause != b->notclause)
  355.       return(false);
  356. #ifdef EqualMergeOrderExists
  357.     if (!EqualMergeOrder(a->mergesortorder,b->mergesortorder))
  358.       return(false);
  359. #endif
  360.     if(a->hashjoinoperator != b->hashjoinoperator)
  361.       return(false);
  362.     return(equal((Node)(a->indexids),
  363.          (Node)(b->indexids)));
  364. }
  365.  
  366. bool
  367. _equalJoinMethod(a,b)
  368.      register JoinMethod a,b;
  369. {
  370.     Assert(IsA(a,JoinMethod));
  371.     Assert(IsA(b,JoinMethod));
  372.  
  373.     if (!equal((Node)(a->jmkeys),
  374.            (Node)(b->jmkeys)))
  375.       return(false);
  376.     if (!equal((Node)(a->clauses),
  377.            (Node)(b->clauses)))
  378.       return(false);
  379.     return(true);
  380. }
  381.  
  382. bool
  383. _equalPath(a,b)
  384. register Path a,b;
  385. {
  386.     Assert(IsA(a,Path));
  387.     Assert(IsA(b,Path));
  388.  
  389.     if (a->pathtype != b->pathtype)
  390.     return(false);
  391.     if (a->parent != b->parent)
  392.     return(false);
  393.     /*
  394.     if (a->path_cost != b->path_cost)
  395.         return(false);
  396.     */
  397.     if (!equal((Node)(a->p_ordering), 
  398.            (Node)(b->p_ordering)))
  399.     return(false);
  400.     if (!equal((Node)(a->keys),
  401.            (Node)(b->keys)))
  402.     return(false);
  403.     if (!equal((Node)(a->pathsortkey),
  404.            (Node)(b->pathsortkey)))
  405.     return(false);
  406.     /*
  407.     if (a->outerjoincost != b->outerjoincost)
  408.     return(false);
  409.     */
  410.     if (!equal((Node)(a->joinid),
  411.            (Node)(b->joinid)))
  412.     return(false);
  413.     return(true);
  414. }
  415.  
  416. bool
  417. _equalIndexPath(a,b)
  418. register IndexPath a,b;
  419. {
  420.     Assert(IsA(a,IndexPath));
  421.     Assert(IsA(b,IndexPath));
  422.  
  423.     if (!_equalPath((Path)a,(Path)b))
  424.     return(false);
  425.     if (!equal((Node)(a->indexid), (Node)(b->indexid)))
  426.     return(false);
  427.     if (!equal((Node)(a->indexqual), (Node)(b->indexqual)))
  428.     return(false);
  429.     return(true);
  430. }
  431.  
  432. bool
  433. _equalJoinPath(a,b)
  434. register JoinPath a,b;
  435. {
  436.     Assert(IsA(a,JoinPath));
  437.     Assert(IsA(b,JoinPath));
  438.  
  439.     if (!_equalPath((Path)a,(Path)b))
  440.     return(false);
  441.     if (!equal((Node)(a->pathclauseinfo), (Node)(b->pathclauseinfo)))
  442.     return(false);
  443.     if (!equal((Node)(a->outerjoinpath), (Node)(b->outerjoinpath)))
  444.     return(false);
  445.     if (!equal((Node)(a->innerjoinpath), (Node)(b->innerjoinpath)))
  446.     return(false);
  447.     return(true);
  448. }
  449.  
  450. bool
  451. _equalMergePath(a,b)
  452. register MergePath a,b;
  453. {
  454.     Assert(IsA(a,MergePath));
  455.     Assert(IsA(b,MergePath));
  456.  
  457.     if (!_equalJoinPath((JoinPath)a,(JoinPath)b))
  458.     return(false);
  459.     if (!equal((Node)(a->path_mergeclauses), (Node)(b->path_mergeclauses)))
  460.     return(false);
  461.     if (!equal((Node)(a->outersortkeys), (Node)(b->outersortkeys)))
  462.     return(false);
  463.     if (!equal((Node)(a->innersortkeys), (Node)(b->innersortkeys)))
  464.     return(false);
  465.     return(true);
  466. }
  467.  
  468. bool
  469. _equalHashPath(a,b)
  470. register HashPath a,b;
  471. {
  472.     Assert(IsA(a,HashPath));
  473.     Assert(IsA(b,HashPath));
  474.  
  475.     if (!_equalJoinPath((JoinPath)a,(JoinPath)b))
  476.     return(false);
  477.     if (!equal((Node)(a->path_hashclauses), (Node)(b->path_hashclauses)))
  478.     return(false);
  479.     if (!equal((Node)(a->outerhashkeys), (Node)(b->outerhashkeys)))
  480.     return(false);
  481.     if (!equal((Node)(a->innerhashkeys), (Node)(b->innerhashkeys)))
  482.     return(false);
  483.     return(true);
  484. }
  485.  
  486. bool
  487. _equalJoinKey(a,b)
  488. register JoinKey a,b;
  489. {
  490.     Assert(IsA(a,JoinKey));
  491.     Assert(IsA(b,JoinKey));
  492.  
  493.     if (!equal((Node)(a->outer),(Node)(b->outer)))
  494.        return(false);
  495.     if (!equal((Node)(a->inner),(Node)(b->inner)))
  496.        return(false);
  497.     return(true);
  498. }
  499.  
  500. bool
  501. _equalMergeOrder(a,b)
  502.      register MergeOrder a,b;
  503. {
  504.     if (a == (MergeOrder)NULL && b == (MergeOrder)NULL)
  505.        return(true);
  506.     Assert(IsA(a,MergeOrder));
  507.     Assert(IsA(b,MergeOrder));
  508.  
  509.     if (a->join_operator != b->join_operator)
  510.       return(false);
  511.     if (a->left_operator != b->left_operator)
  512.       return(false);
  513.     if (a->right_operator != b->right_operator)
  514.       return(false);
  515.     if (a->left_type != b->left_type)
  516.       return(false);
  517.     if (a->right_type != b->right_type)
  518.       return(false);
  519.     return(true);
  520. }
  521.  
  522. bool
  523. _equalHInfo(a,b)
  524.      register HInfo a,b;
  525. {
  526.     Assert(IsA(a,HInfo));
  527.     Assert(IsA(b,HInfo));
  528.  
  529.     if (a->hashop != b->hashop)
  530.       return(false);
  531.     return(true);
  532. }
  533.  
  534. /* XXX  This equality function is a quick hack, should be
  535.  *      fixed to compare all fields.
  536.  */
  537.  
  538. bool
  539. _equalIndexScan(a,b)
  540.      register IndexScan a,b;
  541. {
  542.     Assert(IsA(a,IndexScan));
  543.     Assert(IsA(b,IndexScan));
  544.  
  545.     if(a->cost != b->cost)
  546.       return(false);
  547.  
  548.     if (a->fragment != b->fragment)
  549.       return(false);
  550.  
  551.     if (!equal((Node)(a->indxqual),(Node)(b->indxqual)))
  552.       return(false);
  553.  
  554.     if (a->scanrelid != b->scanrelid)
  555.       return(false);
  556.  
  557.     if (!equal((Node)(a->indxid),(Node)(b->indxid)))
  558.       return(false);
  559.     return(true);
  560. }
  561.  
  562. bool
  563. _equalJInfo(a,b)
  564.      register JInfo a,b;
  565. {
  566.     Assert(IsA(a,JInfo));
  567.     Assert(IsA(b,JInfo));
  568.     if (!equal((Node)(a->otherrels),(Node)(b->otherrels)))
  569.       return(false);
  570.     if (!equal((Node)(a->jinfoclauseinfo),(Node)(b->jinfoclauseinfo)))
  571.       return(false);
  572.     if (a->mergesortable != b->mergesortable)
  573.       return(false);
  574.     if (a->hashjoinable != b->hashjoinable)
  575.       return(false);
  576.     return(true);
  577. }
  578. /*
  579.  *  Stuff from execnodes.h
  580.  */
  581.  
  582. /*
  583.  *  EState is a subclass of Node.
  584.  */
  585.  
  586. bool
  587. _equalEState(a, b)
  588.     register EState    a;
  589.     register EState    b;
  590. {
  591.     if (a->es_direction != b->es_direction)
  592.         return (false);
  593.     if (a->es_time != b->es_time)
  594.         return (false);
  595.     if (a->es_owner != b->es_owner)
  596.         return (false);
  597.     if (!_equalLispValue(a->es_locks, b->es_locks))
  598.         return (false);
  599.     if (!_equalLispValue(a->es_subplan_info, b->es_subplan_info))
  600.         return (false);
  601.     if (a->es_error_message == (Name) NULL
  602.         || b->es_error_message == (Name) NULL) {
  603.         if (a->es_error_message != b->es_error_message)
  604.             return (false);
  605.     } else {
  606.         if (strcmp(a->es_error_message, b->es_error_message) != 0)
  607.             return (false);
  608.     }
  609.     if (!_equalLispValue(a->es_range_table, b->es_range_table))
  610.         return (false);
  611.  
  612.     if (!_equalHeapTuple(a->es_qualification_tuple,
  613.                  b->es_qualification_tuple))
  614.         return (false);
  615.     if (!ItemPointerEquals(a->es_qualification_tuple_id,
  616.                    b->es_qualification_tuple_id))
  617.         return (false);
  618.     if (!_equalRelation(a->es_relation_relation_descriptor,
  619.                 b->es_relation_relation_descriptor))
  620.         return (false);
  621.     if (a->es_result_relation_info != b->es_result_relation_info)
  622.         return (false);
  623.  
  624.     return (true);
  625. }
  626.  
  627. /*
  628.  *  _equalHeapTuple -- Are two heap tuples equal?
  629.  */
  630.  
  631. bool
  632. _equalHeapTuple(a, b)
  633.     register HeapTuple    a;
  634.     register HeapTuple    b;
  635. {
  636.     if (a->t_len != b->t_len)
  637.         return (false);
  638.     if (!ItemPointerEquals(&a->t_ctid, &b->t_ctid))
  639.         return (false);
  640.  
  641.     /*
  642.      *  We ignore the t_lock entry, because i don't know how to
  643.      *  decide which entry in the union to look at.
  644.      */
  645.  
  646.     if (a->t_oid != b->t_oid)
  647.         return (false);
  648.     if (a->t_xmin != b->t_xmin)
  649.         return (false);
  650.     if (a->t_cmin != b->t_cmin)
  651.         return (false);
  652.     if (a->t_xmax != b->t_xmax)
  653.         return (false);
  654.     if (a->t_cmax != b->t_cmax)
  655.         return (false);
  656.  
  657.     if (!ItemPointerEquals(&a->t_chain, &b->t_chain))
  658.         return (false);
  659.     if (a->t_tmin != b->t_tmin)
  660.         return (false);
  661.     if (a->t_tmax != b->t_tmax)
  662.         return (false);
  663.     if (a->t_natts != b->t_natts)
  664.         return (false);
  665.     if (a->t_hoff != b->t_hoff)
  666.         return (false);
  667.     if (a->t_vtype != b->t_vtype)
  668.         return (false);
  669.  
  670.     /*
  671.      *  We ignore the t_bits field, because i don't know how to
  672.      *  compute its length.
  673.      */
  674.  
  675.     return (true);
  676. }
  677.  
  678. /*
  679.  *  _equalRelation -- Are two relations equal?
  680.  *
  681.  *    Two relations are considered equal, for our purposes, if they
  682.  *    have the same object id.  This may not be sufficient, in which
  683.  *    case we can write more code.
  684.  */
  685.  
  686. bool
  687. _equalRelation(a, b)
  688.     Relation    a;
  689.     Relation    b;
  690. {
  691.     if (a->rd_id != b->rd_id)
  692.         return (false);
  693.  
  694.     return (true);
  695. }
  696. /*
  697.  *  _equalLispValue -- are two lists equal?
  698.  *
  699.  *    This is a comparison by value.  It would be simpler to write it
  700.  *    to be recursive, but it should run faster if we iterate.
  701.  */
  702.  
  703. bool
  704. _equalLispValue(a, b)
  705.     register LispValue    a;
  706.     register LispValue    b;
  707. {
  708.     while (a != (LispValue) NULL) {
  709.  
  710.         if (b == (LispValue) NULL)
  711.             return (false);
  712.         if (a == b)
  713.             return(true);
  714.         if (LISP_TYPE(a) != LISP_TYPE(b))
  715.             return (false);
  716.  
  717.         switch (LISP_TYPE(a)) {
  718.  
  719.           case PGLISP_ATOM:
  720.             if (a->val.name != b->val.name)
  721.                 return (false);
  722.             break;
  723.  
  724.           case PGLISP_DTPR:
  725.             if (!_equalLispValue(a->val.car, b->val.car))
  726.                 return (false);
  727.             break;
  728.  
  729.           case PGLISP_FLOAT:
  730.             if (a->val.flonum != b->val.flonum)
  731.                 return (false);
  732.             break;
  733.  
  734.           case PGLISP_INT:
  735.             if (a->val.fixnum != b->val.fixnum)
  736.                 return (false);
  737.             break;
  738.  
  739.           case PGLISP_STR:
  740.             if (strcmp(a->val.str, b->val.str) != 0)
  741.                 return (false);
  742.             break;
  743.  
  744.           case PGLISP_VECI:
  745.             if (a->val.veci->size != b->val.veci->size)
  746.                 return (false);
  747.             if (bcmp(&(a->val.veci->data[0]), &(b->val.veci->data[0]),
  748.                     a->val.veci->size) != 0)
  749.                 return (false);
  750.             break;
  751.  
  752.           default:
  753.             if (IsA(a,Node) && IsA(b,Node) ) 
  754.               if(NodeType(a) == NodeType(b)) {
  755.                  return((*(a->equalFunc))(a,b));
  756.               } else {
  757.                 return(false);
  758.               }
  759.             elog(NOTICE,"equal: LispAtom type %d unknown",
  760.                 a->type);
  761.             return (false);
  762.         }
  763.  
  764.         /* next */
  765.         a = CDR(a);
  766.         b = CDR(b);
  767.     }
  768.  
  769.     if (b != (LispValue) NULL)
  770.         return (false);
  771.  
  772.     return (true);
  773. }
  774.  
  775. bool
  776. _equalFragment(a,b)
  777. register Fragment a,b;
  778. {
  779.     Assert(IsA(a,Fragment));
  780.     Assert(IsA(b,Fragment));
  781.     if (a->frag_root != b->frag_root)
  782.     return(false);
  783.     if (a->frag_parent_op != b->frag_parent_op)
  784.     return(false);
  785.     if (a->frag_parallel != b->frag_parallel)
  786.     return(false);
  787.     if (!equal((Node)(a->frag_subtrees),(Node)(b->frag_subtrees)))
  788.     return(false);
  789.     if (a->frag_parent_frag != b->frag_parent_frag)
  790.     return(false);
  791.     return(true);
  792. }
  793.  
  794.  
  795.  
  796.